home *** CD-ROM | disk | FTP | other *** search
- Subject: v23i025: The SC Spreadsheet, release 6.8, Part05/06
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 191a9280 14982b2b efb671e4 f64ffc17
-
- Submitted-by: Jeff Buhrt <sawmill!buhrt>
- Posting-number: Volume 23, Issue 25
- Archive-name: sc6.8/part05
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: CHANGES eres.sed gram.y psc.doc range.c sc.h version.c
- # vi.c vmtbl.c
- # Wrapped by rsalz@litchi.bbn.com on Fri Jul 13 15:24:22 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 5 (of 6)."'
- if test -f 'CHANGES' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'CHANGES'\"
- else
- echo shar: Extracting \"'CHANGES'\" \(5088 characters\)
- sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
- XCHANGES BETWEEN 6.1 and 6.7
- X
- XDave Lewis -
- X Found and fixed a null pointer derefrece in the 'R' command.
- X
- XRob McMahon -
- X Changed the ctl() macro to work with ANSI style compilers.
- X Cleaned up some non-readonly text problems.
- X
- XRick Linck -
- X Fixed a bug in lex.c - Ann Arbor Ambassadors have long ks and ke
- X termcap entries.
- X
- XSam Drake -
- X A fix for undefined C_* symbols in AIX.
- X
- XPeter Brower -
- X Cleaned up the INTERNATIONAL ifdefs with more portable code.
- X
- XGlen Ditchfield
- X Cleaned up a problem in crypt.c when the encrypted file shrank.
- X
- XBob Bond -
- X Vi style editing for the command line.
- X A bug in range name aliases.
- X
- XJeff Buhrt -
- X -Added "~" filename expansion.
- X -702 columns (A-ZZ) and unlimited rows/cells based on max. memory
- X -fixed a few bugs
- X -slightly decreased CPU usage
- X -MAKES backup copies of files
- X -understands ~$HOME stuff
- X
- XCHANGES BETWEEN 5.1 and 6.1:
- X
- XAndy Valencia -
- X xmalloc aligns data to a double boundary.
- X
- XLawrence Cipriani -
- X Fixed a bug in the "do you want to save this" sequence.
- X
- XSoren Lundsgaard -
- X A null pointer derefrence.
- X
- XRick Perry -
- X Cleaned up a problem with modchk() in sc.c.
- X
- XGregory Bond -
- X Added code for multi argument versions of @min and @max.
- X
- XTad Mannes -
- X Added code to save/restore hidden rows and columns when the
- X data base is saved or restored.
- X
- XMarius Olafsson -
- X INTERNATIONAL changes. Allows full 8 bit characters (if
- X curses supports them.)
- X
- XKurt Horton -
- X Added support for @pv, @fv and @pmt financial functins.
- X Tested lots of different systems, linting.
- X
- XJohn Campbell -
- X Support for VMS. See VMS_NOTES.
- X
- XPeter King -
- X User selection of row or column order for recalculation.
- X Also affects order of traversing regions in /f and /r
- X User setting of automatic or manual recalculation.
- X User setting of number of times to try recalculation.
- X + and - commands when in non-numeric mode to do
- X increment and decrement operations.
- X @index, @stindex, @atan2, @lookup functions.
- X Save/restore options.
- X Support for TeX, LaTeX, and better support for tbl in "T" cmd.
- X Provision of a copyent function to copy entries (same code repeated
- X in several locations)
- X Forwrow, backrow, forwcol, backcol functions to replace
- X repeated code
- X Correct interpretation of ESCAPE or ^G as an abort when in a
- X two character command such as 'ar' or 'ac'
- X Cleanup in eval() - catches non-trap function errors.
- X
- XBob Bond -
- X Added search options to "g".
- X Added supression of hidden columns to "W"
- X Added the mod operator "%"
- X New help functions.
- X Constant prescale "$"
- X Added string matching to @lookup.
- X Some more bug fixes.
- X Testing, integration, documentation.
- X
- XAlan Silverstein-
- X Greatly revised the manual entry.
- X Added menus for ^E command and row/column commands, which
- X involved a bunch of code cleanup.
- X
- X Changed top row display to clearly indicate string labels
- X versus number parts, and to distinguish string functions from
- X constant labels.
- X
- X When the character cursor is on a cell (not topline), ^H
- X (backspace) is like ^B (move back one cell), rather than being
- X ignored.
- X
- X When the character cursor is on a cell (not topline), ^I (tab)
- X is like ^F (move forward one cell), rather than being ignored.
- X ^R is no longer identical with ^L. Now ^R highlights all cells
- X which should be entered by a user because they contain constant
- X numeric values (not the result of a numeric expression).
- X
- X Added a ^X command, similar to ^R, which highlights cells which
- X have expressions. It also displays the expressions in the
- X highlighted cells as left-justified strings, instead of the
- X label and/or value of the cell.
- X
- X Added indirection functions (@nval() and @sval()) for simple
- X table lookups. Given a column name and row number, they return
- X the numeric or string value of the selected cell.
- X
- X Added external functions (@ext()) for non-trivial
- X computations. Given a command name and argument, it calls the
- X command and reads back one output line.
- X
- X Added a ^T,e command to toggle enabling of external functions.
- X
- X Changed ^T,t to only control the top line display, and added
- X ^T,c to control current cell highlighting. (Separated the
- X functions.)
- X
- X "!" (shell escape) gives a vi-style warning if there were any
- X changes since the last write. (No change to manual entry.)
- X
- X Fixed some startup, error, and prompt messages to be cleaner
- X and/or more consistent. (No changes to manual entry.)
- X
- X Fixed a bug: If @substr() upper bound (third parameter) is
- X past the end of the string operand, return the substring
- X through the end of the string, rather than returning a null
- X string.
- X
- X Fixed a bug: Reset SIGINT to default after forking before
- X calling shell escape program and before starting pipeline (for
- X commands which support this). Didn't reset SIGINT before
- X calling crypt and external functions because in both cases it
- X should be irrelevant. (No change to manual entry.)
- X
- XCHANGES BETWEEN 6.1 and 6.2:
- X
- X
- XChris Cole-
- X Compatibility with Lotus 1-2-3
- X a) @hlookup(expr,range,expr)
- X b) @vlookup(expr,range,expr)
- X c) @round(expr,expr)
- X d) @if(expr,expr,expr)
- X e) @abs(expr)
- END_OF_FILE
- if test 5088 -ne `wc -c <'CHANGES'`; then
- echo shar: \"'CHANGES'\" unpacked with wrong size!
- fi
- # end of 'CHANGES'
- fi
- if test -f 'eres.sed' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'eres.sed'\"
- else
- echo shar: Extracting \"'eres.sed'\" \(50 characters\)
- sed "s/^X//" >'eres.sed' <<'END_OF_FILE'
- X/%token.*K_/!d
- X/%token.*K_\(.*\)/s// "\1", K_\1,/
- END_OF_FILE
- if test 50 -ne `wc -c <'eres.sed'`; then
- echo shar: \"'eres.sed'\" unpacked with wrong size!
- fi
- # end of 'eres.sed'
- fi
- if test -f 'gram.y' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'gram.y'\"
- else
- echo shar: Extracting \"'gram.y'\" \(12082 characters\)
- sed "s/^X//" >'gram.y' <<'END_OF_FILE'
- X/* SC A Spreadsheet Calculator
- X * Command and expression parser
- X *
- X * original by James Gosling, September 1982
- X * modified by Mark Weiser and Bruce Israel,
- X * University of Maryland
- X *
- X * more mods Robert Bond 12/86
- X *
- X * More mods by Alan Silverstein, 3/88, see list of changes.
- X *
- X * $Revision: 6.8 $
- X */
- X
- X
- X
- X%{
- X#include <curses.h>
- X#include "sc.h"
- X
- X#define ENULL (struct enode *)0
- X
- Xchar *strcpy();
- X%}
- X
- X%union {
- X int ival;
- X double fval;
- X struct ent_ptr ent;
- X struct enode *enode;
- X char *sval;
- X struct range_s rval;
- X}
- X
- X%type <ent> var
- X%type <fval> num
- X%type <rval> range
- X%type <rval> var_or_range
- X%type <sval> strarg
- X%type <enode> e term expr_list
- X%token <sval> STRING
- X%token <ival> NUMBER
- X%token <fval> FNUMBER
- X%token <rval> RANGE
- X%token <rval> VAR
- X%token <sval> WORD
- X%token <ival> COL
- X%token S_FORMAT
- X%token S_LABEL
- X%token S_LEFTSTRING
- X%token S_RIGHTSTRING
- X%token S_GET
- X%token S_PUT
- X%token S_MERGE
- X%token S_LET
- X%token S_WRITE
- X%token S_TBL
- X%token S_COPY
- X%token S_SHOW
- X%token S_ERASE
- X%token S_FILL
- X%token S_GOTO
- X%token S_DEFINE
- X%token S_UNDEFINE
- X%token S_VALUE
- X%token S_MDIR
- X%token S_HIDE
- X%token S_SET
- X
- X%token K_FIXED
- X%token K_SUM
- X%token K_PROD
- X%token K_AVG
- X%token K_STDDEV
- X%token K_COUNT
- X%token K_ABS
- X%token K_ACOS
- X%token K_ASIN
- X%token K_ATAN
- X%token K_ATAN2
- X%token K_CEIL
- X%token K_COS
- X%token K_EXP
- X%token K_FABS
- X%token K_FLOOR
- X%token K_HYPOT
- X%token K_LN
- X%token K_LOG
- X%token K_PI
- X%token K_POW
- X%token K_SIN
- X%token K_SQRT
- X%token K_TAN
- X%token K_DTR
- X%token K_RTD
- X%token K_MAX
- X%token K_MIN
- X%token K_RND
- X%token K_ROUND
- X%token K_IF
- X
- X%token K_PV
- X%token K_FV
- X%token K_PMT
- X
- X%token K_HOUR
- X%token K_MINUTE
- X%token K_SECOND
- X%token K_MONTH
- X%token K_DAY
- X%token K_YEAR
- X%token K_NOW
- X%token K_DATE
- X%token K_DTS
- X%token K_TTS
- X%token K_FMT
- X%token K_SUBSTR
- X%token K_STON
- X%token K_EQS
- X%token K_EXT
- X%token K_NVAL
- X%token K_SVAL
- X%token K_LOOKUP
- X%token K_HLOOKUP
- X%token K_VLOOKUP
- X%token K_INDEX
- X%token K_STINDEX
- X%token K_AUTO
- X%token K_AUTOCALC
- X%token K_BYROWS
- X%token K_BYCOLS
- X%token K_BYGRAPH
- X%token K_ITERATIONS
- X%token K_NUMERIC
- X%token K_PRESCALE
- X%token K_EXTFUN
- X%token K_CELLCUR
- X%token K_TOPROW
- X%token K_TBLSTYLE
- X%token K_TBL
- X%token K_LATEX
- X%token K_TEX
- X
- X%left '?' ':'
- X%left '|'
- X%left '&'
- X%nonassoc '<' '=' '>' '!'
- X%left '+' '-' '#'
- X%left '*' '/' '%'
- X%left '^'
- X
- X%%
- Xcommand: S_LET var_or_range '=' e
- X { let($2.left.vp, $4); }
- X | S_LABEL var_or_range '=' e
- X { slet($2.left.vp, $4, 0); }
- X | S_LEFTSTRING var_or_range '=' e
- X { slet($2.left.vp, $4, -1); }
- X | S_RIGHTSTRING var_or_range '=' e
- X { slet($2.left.vp, $4, 1); }
- X | S_FORMAT COL ':' COL NUMBER NUMBER
- X { doformat($2,$4,$5,$6); }
- X | S_FORMAT COL NUMBER NUMBER
- X { doformat($2,$2,$3,$4); }
- X | S_GET strarg { /* This tmp hack is because readfile
- X * recurses back through yyparse. */
- X char *tmp;
- X tmp = $2;
- X readfile (tmp, 1);
- X xfree(tmp);
- X }
- X | S_MERGE strarg {
- X char *tmp;
- X tmp = $2;
- X readfile (tmp, 0);
- X xfree(tmp);
- X }
- X | S_MDIR strarg
- X { if (mdir) xfree(mdir); mdir = $2; }
- X | S_PUT strarg range
- X { (void) writefile($2, ($3.left.vp)->row,
- X ($3.left.vp)->col, ($3.right.vp)->row,
- X ($3.right.vp)->col);
- X xfree($2); }
- X | S_PUT strarg
- X { (void) writefile ($2, 0, 0, maxrow, maxcol);
- X xfree($2); }
- X | S_WRITE strarg range { (void) printfile($2, ($3.left.vp)->row,
- X ($3.left.vp)->col, ($3.right.vp)->row,
- X ($3.right.vp)->col);
- X xfree($2); }
- X | S_WRITE strarg { (void) printfile ($2, 0, 0, maxrow, maxcol);
- X xfree($2); }
- X | S_TBL strarg range { (void) tblprintfile($2, ($3.left.vp)->row,
- X ($3.left.vp)->col, ($3.right.vp)->row,
- X ($3.right.vp)->col);
- X xfree($2); }
- X | S_TBL strarg { (void)tblprintfile ($2, 0, 0, maxrow, maxcol);
- X xfree($2); }
- X | S_SHOW COL ':' COL
- X { showcol( $2, $4); }
- X | S_SHOW NUMBER ':' NUMBER
- X { showrow( $2, $4); }
- X | S_HIDE COL
- X { hide_col( $2 ); }
- X | S_HIDE NUMBER
- X { hide_row( $2 ); }
- X | S_COPY range var_or_range
- X { copy($2.left.vp,$2.right.vp,
- X $3.left.vp,$3.right.vp); }
- X | S_ERASE
- X { eraser(lookat(showsr, showsc),
- X lookat(currow, curcol)); }
- X | S_ERASE var_or_range
- X { eraser($2.left.vp, $2.right.vp); }
- X | S_VALUE { valueize_area(showsr, showsc, currow, curcol);
- X modflg++; }
- X | S_VALUE var_or_range { valueize_area(($2.left.vp)->row,
- X ($2.left.vp)->col,
- X ($2.right.vp)->row,
- X ($2.right.vp)->col); modflg++; }
- X | S_FILL num num { fill(lookat(showsr, showsc),
- X lookat(currow, curcol), $2, $3); }
- X | S_FILL var_or_range num num
- X { fill($2.left.vp, $2.right.vp, $3, $4); }
- X | S_GOTO var_or_range {moveto($2.left.vp->row, $2.left.vp->col);}
- X | S_GOTO num {num_search($2);}
- X | S_GOTO STRING {str_search($2);}
- X | S_GOTO {go_last();}
- X | S_DEFINE strarg { struct ent_ptr arg1, arg2;
- X arg1.vp = lookat(showsr, showsc);
- X arg1.vf = 0;
- X arg2.vp = lookat(currow, curcol);
- X arg2.vf = 0;
- X add_range($2, arg1, arg2, 1); }
- X
- X | S_DEFINE strarg range { add_range($2, $3.left, $3.right, 1); }
- X | S_DEFINE strarg var { add_range($2, $3, $3, 0); }
- X | S_UNDEFINE var_or_range { del_range($2.left.vp, $2.right.vp); }
- X | S_SET setlist
- X | /* nothing */
- X | error;
- X
- Xterm: var { $$ = new_var('v', $1); }
- X | K_FIXED term { $$ = new ('f', ENULL, $2); }
- X | '@' K_SUM '(' var_or_range ')'
- X { $$ = new_range(REDUCE | '+', $4); }
- X | '@' K_PROD '(' var_or_range ')'
- X { $$ = new_range (REDUCE | '*', $4); }
- X | '@' K_AVG '(' var_or_range ')'
- X { $$ = new_range (REDUCE | 'a', $4); }
- X | '@' K_STDDEV '(' var_or_range ')'
- X { $$ = new_range (REDUCE | 's', $4); }
- X | '@' K_COUNT '(' var_or_range ')'
- X { $$ = new_range (REDUCE | 'c', $4); }
- X | '@' K_MAX '(' var_or_range ')'
- X { $$ = new_range (REDUCE | MAX, $4); }
- X | '@' K_MAX '(' e ',' expr_list ')'
- X { $$ = new(LMAX, $6, $4); }
- X | '@' K_MIN '(' var_or_range ')'
- X { $$ = new_range (REDUCE | MIN, $4); }
- X | '@' K_MIN '(' e ',' expr_list ')'
- X { $$ = new(LMIN, $6, $4); }
- X | '@' K_ABS '(' e ')' { $$ = new(ABS, ENULL, $4); }
- X | '@' K_ACOS '(' e ')' { $$ = new(ACOS, ENULL, $4); }
- X | '@' K_ASIN '(' e ')' { $$ = new(ASIN, ENULL, $4); }
- X | '@' K_ATAN '(' e ')' { $$ = new(ATAN, ENULL, $4); }
- X | '@' K_ATAN2 '(' e ',' e ')' { $$ = new(ATAN2, $4, $6); }
- X | '@' K_CEIL '(' e ')' { $$ = new(CEIL, ENULL, $4); }
- X | '@' K_COS '(' e ')' { $$ = new(COS, ENULL, $4); }
- X | '@' K_EXP '(' e ')' { $$ = new(EXP, ENULL, $4); }
- X | '@' K_FABS '(' e ')' { $$ = new(FABS, ENULL, $4); }
- X | '@' K_FLOOR '(' e ')' { $$ = new(FLOOR, ENULL, $4); }
- X | '@' K_HYPOT '(' e ',' e ')' { $$ = new(HYPOT, $4, $6); }
- X | '@' K_LN '(' e ')' { $$ = new(LOG, ENULL, $4); }
- X | '@' K_LOG '(' e ')' { $$ = new(LOG10, ENULL, $4); }
- X | '@' K_POW '(' e ',' e ')' { $$ = new(POW, $4, $6); }
- X | '@' K_SIN '(' e ')' { $$ = new(SIN, ENULL, $4); }
- X | '@' K_SQRT '(' e ')' { $$ = new(SQRT, ENULL, $4); }
- X | '@' K_TAN '(' e ')' { $$ = new(TAN, ENULL, $4); }
- X | '@' K_DTR '(' e ')' { $$ = new(DTR, ENULL, $4); }
- X | '@' K_RTD '(' e ')' { $$ = new(RTD, ENULL, $4); }
- X | '@' K_RND '(' e ')' { $$ = new(RND, ENULL, $4); }
- X | '@' K_ROUND '(' e ',' e ')' { $$ = new(ROUND, $4, $6); }
- X | '@' K_IF '(' e ',' e ',' e ')' { $$ = new(IF, $4,new(',',$6,$8)); }
- X
- X | '@' K_PV '(' e ',' e ',' e ')' { $$ = new(PV, $4,new(':',$6,$8)); }
- X | '@' K_FV '(' e ',' e ',' e ')' { $$ = new(FV, $4,new(':',$6,$8)); }
- X | '@' K_PMT '(' e ',' e ',' e ')' { $$ = new(PMT, $4,new(':',$6,$8)); }
- X
- X | '@' K_HOUR '(' e ')' { $$ = new(HOUR,ENULL, $4); }
- X | '@' K_MINUTE '(' e ')' { $$ = new(MINUTE,ENULL, $4); }
- X | '@' K_SECOND '(' e ')' { $$ = new(SECOND,ENULL, $4); }
- X | '@' K_MONTH '(' e ')' { $$ = new(MONTH,ENULL,$4); }
- X | '@' K_DAY '(' e ')' { $$ = new(DAY, ENULL, $4); }
- X | '@' K_YEAR '(' e ')' { $$ = new(YEAR, ENULL, $4); }
- X | '@' K_NOW { $$ = new(NOW, ENULL, ENULL);}
- X | '@' K_DTS '(' e ',' e ',' e ')'
- X { $$ = new(DTS, $4, new(',', $6, $8));}
- X | '@' K_TTS '(' e ',' e ',' e ')'
- X { $$ = new(TTS, $4, new(',', $6, $8));}
- X | '@' K_STON '(' e ')' { $$ = new(STON, ENULL, $4); }
- X | '@' K_EQS '(' e ',' e ')' { $$ = new (EQS, $4, $6); }
- X | '@' K_DATE '(' e ')' { $$ = new(DATE, ENULL, $4); }
- X | '@' K_FMT '(' e ',' e ')' { $$ = new(FMT, $4, $6); }
- X | '@' K_INDEX '(' e ',' var_or_range ')'
- X { $$ = new(INDEX, $4, new_range(REDUCE | INDEX, $6)); }
- X | '@' K_LOOKUP '(' e ',' var_or_range ')'
- X { $$ = new(LOOKUP, $4, new_range(REDUCE | LOOKUP, $6)); }
- X | '@' K_HLOOKUP '(' e ',' var_or_range ',' e ')'
- X { $$ = new(HLOOKUP, new(',', $4, $8),
- X new_range(REDUCE | HLOOKUP, $6)); }
- X | '@' K_VLOOKUP '(' e ',' var_or_range ',' e ')'
- X { $$ = new(VLOOKUP, new(',', $4, $8),
- X new_range(REDUCE | VLOOKUP, $6)); }
- X | '@' K_STINDEX '(' e ',' var_or_range ')'
- X { $$ = new(STINDEX, $4, new_range(REDUCE | STINDEX, $6)); }
- X | '@' K_EXT '(' e ',' e ')' { $$ = new(EXT, $4, $6); }
- X | '@' K_NVAL '(' e ',' e ')' { $$ = new(NVAL, $4, $6); }
- X | '@' K_SVAL '(' e ',' e ')' { $$ = new(SVAL, $4, $6); }
- X | '@' K_SUBSTR '(' e ',' e ',' e ')'
- X { $$ = new(SUBSTR, $4, new(',', $6, $8)); }
- X | '(' e ')' { $$ = $2; }
- X | '+' term { $$ = $2; }
- X | '-' term { $$ = new ('m', ENULL, $2); }
- X | NUMBER { $$ = new_const('k', (double) $1); }
- X | FNUMBER { $$ = new_const('k', $1); }
- X | K_PI { $$ = new_const('k', (double)3.14159265358979323846); }
- X | STRING { $$ = new_str($1); }
- X | '~' term { $$ = new ('~', ENULL, $2); }
- X | '!' term { $$ = new ('~', ENULL, $2); }
- X ;
- X
- Xe: e '+' e { $$ = new ('+', $1, $3); }
- X | e '-' e { $$ = new ('-', $1, $3); }
- X | e '*' e { $$ = new ('*', $1, $3); }
- X | e '/' e { $$ = new ('/', $1, $3); }
- X | e '%' e { $$ = new ('%', $1, $3); }
- X | e '^' e { $$ = new ('^', $1, $3); }
- X | term
- X | e '?' e ':' e { $$ = new ('?', $1, new(':', $3, $5)); }
- X | e '<' e { $$ = new ('<', $1, $3); }
- X | e '=' e { $$ = new ('=', $1, $3); }
- X | e '>' e { $$ = new ('>', $1, $3); }
- X | e '&' e { $$ = new ('&', $1, $3); }
- X | e '|' e { $$ = new ('|', $1, $3); }
- X | e '<' '=' e { $$ = new ('~', ENULL, new ('>', $1, $4)); }
- X | e '!' '=' e { $$ = new ('~', ENULL, new ('=', $1, $4)); }
- X | e '>' '=' e { $$ = new ('~', ENULL, new ('<', $1, $4)); }
- X | e '#' e { $$ = new ('#', $1, $3); }
- X ;
- X
- Xexpr_list: e { $$ = new(ELIST, ENULL, $1); }
- X | expr_list ',' e { $$ = new(ELIST, $1, $3); }
- X ;
- X
- Xrange: var ':' var { $$.left = $1; $$.right = $3; }
- X | RANGE { $$ = $1; }
- X ;
- X
- Xvar: COL NUMBER { $$.vp = lookat($2 , $1); $$.vf = 0;}
- X | '$' COL NUMBER { $$.vp = lookat($3 , $2);
- X $$.vf = FIX_COL;}
- X | COL '$' NUMBER { $$.vp = lookat($3 , $1);
- X $$.vf = FIX_ROW;}
- X | '$' COL '$' NUMBER { $$.vp = lookat($4 , $2);
- X $$.vf = FIX_ROW | FIX_COL;}
- X | VAR { $$ = $1.left; }
- X ;
- X
- Xvar_or_range: range { $$ = $1; }
- X | var { $$.left = $1; $$.right = $1; }
- X ;
- X
- Xnum: NUMBER { $$ = (double) $1; }
- X | FNUMBER { $$ = $1; }
- X | '-' num { $$ = -$2; }
- X | '+' num { $$ = $2; }
- X ;
- X
- Xstrarg: STRING { $$ = $1; }
- X | var {
- X char *s, *s1;
- X s1 = $1.vp->label;
- X if (!s1)
- X s1 = "NULL_STRING";
- X s = xmalloc((unsigned)strlen(s1)+1);
- X (void) strcpy(s, s1);
- X $$ = s;
- X }
- X ;
- X
- Xsetlist :
- X | setlist setitem
- X ;
- X
- Xsetitem : K_AUTO { setauto(1); }
- X | K_AUTOCALC { setauto(1); }
- X | '~' K_AUTO { setauto(0); }
- X | '~' K_AUTOCALC { setauto(0); }
- X | '!' K_AUTO { setauto(0); }
- X | '!' K_AUTOCALC { setauto(0); }
- X | K_BYCOLS { setorder(BYCOLS); }
- X | K_BYROWS { setorder(BYROWS); }
- X | K_BYGRAPH { setorder(BYGRAPH); }
- X | K_NUMERIC { numeric = 1; }
- X | '!' K_NUMERIC { numeric = 0; }
- X | K_PRESCALE { prescale = 0.01; }
- X | '!' K_PRESCALE { prescale = 1.0; }
- X | K_EXTFUN { extfunc = 1; }
- X | '!' K_EXTFUN { extfunc = 0; }
- X | K_CELLCUR { showcell = 1; }
- X | '!' K_CELLCUR { showcell = 0; }
- X | K_TOPROW { showtop = 1; }
- X | '!' K_TOPROW { showtop = 0; }
- X | K_ITERATIONS '=' NUMBER { setiterations($3); }
- X | K_TBLSTYLE '=' NUMBER { tbl_style = $3; }
- X | K_TBLSTYLE '=' K_TBL { tbl_style = TBL; }
- X | K_TBLSTYLE '=' K_LATEX { tbl_style = LATEX; }
- X | K_TBLSTYLE '=' K_TEX { tbl_style = TEX; }
- X ;
- END_OF_FILE
- if test 12082 -ne `wc -c <'gram.y'`; then
- echo shar: \"'gram.y'\" unpacked with wrong size!
- fi
- # end of 'gram.y'
- fi
- if test -f 'psc.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'psc.doc'\"
- else
- echo shar: Extracting \"'psc.doc'\" \(2147 characters\)
- sed "s/^X//" >'psc.doc' <<'END_OF_FILE'
- X.\" $Revision $
- X.TH PPNAME 1
- X.SH NAME
- Xppname \- prepare pname files
- X.SH SYNOPSIS
- X.B ppname
- X[
- X.I -fLkr
- X]
- X[
- X.I -s cell
- X]
- X[
- X.I -R n
- X]
- X[
- X.I -C n
- X]
- X[
- X.I -n n
- X]
- X[
- X.I -d c
- X]
- X
- X.SH DESCRIPTION
- X.I Ppname
- Xis used to prepare data for input to the spread sheet calculator
- X.I pname(1).
- XIt accepts normal ascii data on standard input. Standard output
- Xis a
- X.I pname
- Xfile.
- XWith no options,
- X.I ppname
- Xstarts the spread sheet in cell A0. Strings are right justified.
- XAll data on a line is entered on the same row; new input lines
- Xcause the output row number to increment by one. The default delimiters
- Xare tab and space. The column formats are set to one larger
- Xthan the number of columns required to hold the largest value
- Xin the column.
- X
- XOptions:
- X
- X.IP "\-f"
- XOmit column width calculations. This option is for preparing
- Xdata to be merged with an existing spreadsheet. If the option is not
- Xspecified, the column widths calculated for the data read by
- X.I ppname
- Xwill override those already set in the existing spreadsheet.
- X
- X.IP "\-L"
- XLeft justify strings.
- X
- X.IP "\-k"
- XKeep all delimiters. This option causes the output cell to change on
- Xeach new delimiter encountered in the input stream. The default
- Xaction is to condense multiple delimters to one, so that the cell only
- Xchanges once per input data item.
- X
- X.IP "\-r"
- XOutput the data by row first then column. For input consisting of a single
- Xcolumn, this
- Xoption will result in output of one row with multiple columns
- Xinstead of a single
- Xcolumn spread sheet.
- X
- X.IP "\-s cell"
- XStart the top left corner of the spread sheet in
- X.I cell.
- XFor example,
- X.I "-s B33"
- Xwill arrange the output data so that the
- Xspread sheet starts in column B, row 33.
- X
- X.IP "\-R n"
- XIncrement by
- X.I n
- Xon each new output row.
- X
- X.IP "\-C n"
- XIncrement by
- X.I n
- Xon each new output column.
- X
- X.IP "\-n n"
- XOutput
- X.I n
- Xrows before advancing to the next column. This option is used when
- Xthe input is arranged in a single column and the spread sheet is to
- Xhave multiple columns, each of which is to be length
- X.I n.
- X
- X.IP "\-d c"
- XUse the single character
- X.I c
- Xas the delimiter between input fields.
- X
- X.SH SEE ALSO
- Xpname(1)
- X
- X.SH AUTHOR
- X
- XRobert Bond
- END_OF_FILE
- if test 2147 -ne `wc -c <'psc.doc'`; then
- echo shar: \"'psc.doc'\" unpacked with wrong size!
- fi
- # end of 'psc.doc'
- fi
- if test -f 'range.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'range.c'\"
- else
- echo shar: Extracting \"'range.c'\" \(5604 characters\)
- sed "s/^X//" >'range.c' <<'END_OF_FILE'
- X
- X/* SC A Spreadsheet Calculator
- X * Range Manipulations
- X *
- X * Robert Bond, 4/87
- X *
- X * $Revision: 6.8 $
- X */
- X
- X#include <stdio.h>
- X#include <curses.h>
- X#include <ctype.h>
- X#include "sc.h"
- X
- X#ifdef BSD42
- X#include <strings.h>
- X#else
- X#ifndef SYSIII
- X#include <string.h>
- X#endif
- X#endif
- X
- Xstatic struct range *rng_base;
- X
- Xadd_range(name, left, right, is_range)
- Xchar *name;
- Xstruct ent_ptr left, right;
- Xint is_range;
- X{
- X struct range *r;
- X register char *p;
- X int len;
- X int minr,minc,maxr,maxc;
- X int minrf, mincf, maxrf, maxcf;
- X
- X if (left.vp->row < right.vp->row) {
- X minr = left.vp->row; minrf = left.vf & FIX_ROW;
- X maxr = right.vp->row; maxrf = right.vf & FIX_ROW;
- X } else {
- X minr = right.vp->row; minrf = right.vf & FIX_ROW;
- X maxr = left.vp->row; maxrf = right.vf & FIX_ROW;
- X }
- X
- X if (left.vp->col < right.vp->col) {
- X minc = left.vp->col; mincf = left.vf & FIX_COL;
- X maxc = right.vp->col; maxcf = right.vf & FIX_COL;
- X } else {
- X minc = right.vp->col; mincf = right.vf & FIX_COL;
- X maxc = left.vp->col; maxcf = left.vf & FIX_COL;
- X }
- X
- X left.vp = lookat(minr, minc);
- X left.vf = minrf | mincf;
- X right.vp = lookat(maxr, maxc);
- X right.vf = maxrf | maxcf;
- X
- X if (find_range(name, strlen(name), (struct ent *)0, (struct ent *)0)) {
- X error("Error: range name already defined");
- X xfree(name);
- X return;
- X }
- X
- X if (strlen(name) <= 2) {
- X error("Invalid range name - too short");
- X xfree(name);
- X return;
- X }
- X
- X for(p=name, len=0; *p; p++, len++)
- X if (!((isalpha(*p) && (len<=2)) ||
- X ((isdigit(*p) || isalpha(*p) || (*p == '_')) && (len>2)))) {
- X error("Invalid range name - illegal combination");
- X xfree(name);
- X return;
- X }
- X
- X r = (struct range *)xmalloc((unsigned)sizeof(struct range));
- X r->r_name = name;
- X r->r_left = left;
- X r->r_right = right;
- X r->r_next = rng_base;
- X r->r_prev = (struct range *)0;
- X r->r_is_range = is_range;
- X if (rng_base)
- X rng_base->r_prev = r;
- X rng_base = r;
- X}
- X
- Xdel_range(left, right)
- Xstruct ent *left, *right;
- X{
- X register struct range *r;
- X int minr,minc,maxr,maxc;
- X
- X minr = left->row < right->row ? left->row : right->row;
- X minc = left->col < right->col ? left->col : right->col;
- X maxr = left->row > right->row ? left->row : right->row;
- X maxc = left->col > right->col ? left->col : right->col;
- X
- X left = lookat(minr, minc);
- X right = lookat(maxr, maxc);
- X
- X if (!(r = find_range((char *)0, 0, left, right)))
- X return;
- X
- X if (r->r_next)
- X r->r_next->r_prev = r->r_prev;
- X if (r->r_prev)
- X r->r_prev->r_next = r->r_next;
- X else
- X rng_base = r->r_next;
- X xfree((char *)(r->r_name));
- X xfree((char *)r);
- X}
- X
- Xclean_range()
- X{
- X register struct range *r;
- X register struct range *nextr;
- X
- X r = rng_base;
- X rng_base = (struct range *)0;
- X
- X while (r) {
- X nextr = r->r_next;
- X xfree((char *)(r->r_name));
- X xfree((char *)r);
- X r = nextr;
- X }
- X}
- X
- X/* Match on name or lmatch, rmatch */
- X
- Xstruct range *
- Xfind_range(name, len, lmatch, rmatch)
- Xchar *name;
- Xint len;
- Xstruct ent *lmatch;
- Xstruct ent *rmatch;
- X{
- X struct range *r;
- X register char *rp, *np;
- X register int c;
- X
- X if (name) {
- X for (r = rng_base; r; r = r->r_next) {
- X for (np = name, rp = r->r_name, c = len;
- X c && *rp && (*rp == *np);
- X rp++, np++, c--) /* */;
- X if (!c && !*rp)
- X return(r);
- X }
- X return((struct range *)0);
- X }
- X
- X for (r = rng_base; r; r= r->r_next) {
- X if ((lmatch == r->r_left.vp) && (rmatch == r->r_right.vp))
- X return(r);
- X }
- X return((struct range *)0);
- X}
- X
- Xsync_ranges()
- X{
- X register struct range *r;
- X
- X r = rng_base;
- X while(r) {
- X r->r_left.vp = lookat(r->r_left.vp->row, r->r_left.vp->col);
- X r->r_right.vp = lookat(r->r_right.vp->row, r->r_right.vp->col);
- X r = r->r_next;
- X }
- X}
- X
- Xwrite_range(f)
- XFILE *f;
- X{
- X register struct range *r;
- X
- X for (r = rng_base; r; r = r->r_next) {
- X (void) fprintf(f, "define \"%s\" %s%s%s%d",
- X r->r_name,
- X r->r_left.vf & FIX_COL ? "$":"",
- X coltoa(r->r_left.vp->col),
- X r->r_left.vf & FIX_ROW ? "$":"",
- X r->r_left.vp->row);
- X if (r->r_is_range)
- X (void) fprintf(f, ":%s%s%s%d\n",
- X r->r_right.vf & FIX_COL ? "$":"",
- X coltoa(r->r_right.vp->col),
- X r->r_right.vf & FIX_ROW ? "$":"",
- X r->r_right.vp->row);
- X else
- X (void) fprintf(f, "\n");
- X }
- X}
- X
- Xvoid
- Xlist_range(f)
- XFILE *f;
- X{
- X register struct range *r;
- X
- X (void) fprintf(f, "%-30s %s\n\n","Name","Definition");
- X
- X for (r = rng_base; r; r = r->r_next) {
- X (void) fprintf(f, "%-30s %s%s%s%d",
- X r->r_name,
- X r->r_left.vf & FIX_COL ? "$":"",
- X coltoa(r->r_left.vp->col),
- X r->r_left.vf & FIX_ROW ? "$":"",
- X r->r_left.vp->row);
- X if (r->r_is_range)
- X (void) fprintf(f, ":%s%s%s%d\n",
- X r->r_right.vf & FIX_COL ? "$":"",
- X coltoa(r->r_right.vp->col),
- X r->r_right.vf & FIX_ROW ? "$":"",
- X r->r_right.vp->row);
- X else
- X (void) fprintf(f, "\n");
- X }
- X}
- X
- Xchar *
- Xv_name(row, col)
- Xint row, col;
- X{
- X struct ent *v;
- X struct range *r;
- X static char buf[20];
- X
- X v = lookat(row, col);
- X if (r = find_range((char *)0, 0, v, v)) {
- X return(r->r_name);
- X } else {
- X (void) sprintf(buf, "%s%d", coltoa(col), row);
- X return(buf);
- X }
- X}
- X
- Xchar *
- Xr_name(r1, c1, r2, c2)
- Xint r1, c1, r2, c2;
- X{
- X struct ent *v1, *v2;
- X struct range *r;
- X static char buf[100];
- X
- X v1 = lookat(r1, c1);
- X v2 = lookat(r2, c2);
- X if (r = find_range((char *)0, 0, v1, v2)) {
- X return(r->r_name);
- X } else {
- X (void) sprintf(buf, "%s", v_name(r1, c1));
- X (void) sprintf(buf+strlen(buf), ":%s", v_name(r2, c2));
- X return(buf);
- X }
- X}
- X
- Xare_ranges()
- X{
- Xreturn (rng_base != 0);
- X}
- END_OF_FILE
- if test 5604 -ne `wc -c <'range.c'`; then
- echo shar: \"'range.c'\" unpacked with wrong size!
- fi
- # end of 'range.c'
- fi
- if test -f 'sc.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sc.h'\"
- else
- echo shar: Extracting \"'sc.h'\" \(8426 characters\)
- sed "s/^X//" >'sc.h' <<'END_OF_FILE'
- X/* SC A Table Calculator
- X * Common definitions
- X *
- X * original by James Gosling, September 1982
- X * modified by Mark Weiser and Bruce Israel,
- X * University of Maryland
- X * R. Bond 12/86
- X * More mods by Alan Silverstein, 3-4/88, see list of changes.
- X * $Revision: 6.8 $
- X *
- X */
- X
- X#define ATBL(tbl, row, col) (*(tbl + row) + (col))
- X
- X#define MINROWS 40 /* minimum size at startup */
- X#define MINCOLS 20
- X#define ABSMAXCOLS 702 /* absolute cols: ZZ (base 26) */
- X#define RESCOL 4 /* columns reserved for row numbers */
- X#define RESROW 3 /* rows reserved for prompt, error, and column numbers */
- X#define DEFWIDTH 10 /* Default column width and precision */
- X#define DEFPREC 2
- X#define HISTLEN 10 /* Number of history entries for vi emulation */
- X#define error (void)move(1,0), (void)clrtoeol(), (void) printw
- X#define FBUFLEN 1024 /* buffer size for a single field */
- X#define PATHLEN 1024 /* maximum path length */
- X
- X#ifndef A_CHARTEXT /* Should be defined in curses.h */
- X#ifdef INTERNATIONAL
- X#define A_CHARTEXT 0xff
- X#else
- X#define A_CHARTEXT 0x7f
- X#endif
- X#endif
- X
- X#if (defined(BSD42) || defined(BSD43)) && !defined(strrchr)
- X#define strrchr rindex
- X#endif
- X
- Xstruct ent_ptr {
- X int vf;
- X struct ent *vp;
- X};
- X
- Xstruct range_s {
- X struct ent_ptr left, right;
- X};
- X
- X/*
- X * Some not too obvious things about the flags:
- X * is_valid means there is a valid number in v.
- X * label set means it points to a valid constant string.
- X * is_strexpr set means expr yields a string expression.
- X * If is_strexpr is not set, and expr points to an expression tree, the
- X * expression yields a numeric expression.
- X * So, either v or label can be set to a constant.
- X * Either (but not both at the same time) can be set from an expression.
- X */
- X
- X#define VALID_CELL(p, r, c) ((p = *ATBL(tbl, r, c)) && \
- X ((p->flags & is_valid) || p->label))
- X
- Xstruct ent {
- X double v;
- X char *label;
- X struct enode *expr;
- X short flags;
- X short row, col;
- X struct ent *next; /* next deleted ent */
- X struct ent *evnext; /* next ent w/ a object to eval */
- X struct ent *evprev; /* prev ent w/ a object to eval */
- X};
- X
- Xstruct range {
- X struct ent_ptr r_left, r_right;
- X char *r_name;
- X struct range *r_next, *r_prev;
- X int r_is_range;
- X};
- X
- X#define FIX_ROW 1
- X#define FIX_COL 2
- X
- Xstruct enode {
- X int op;
- X union {
- X double k;
- X struct ent_ptr v;
- X struct range_s r;
- X char *s;
- X struct {
- X struct enode *left, *right;
- X } o;
- X } e;
- X};
- X
- X/* op values */
- X#define O_VAR 'v'
- X#define O_CONST 'k'
- X#define O_SCONST '$'
- X#define REDUCE 0200 /* Or'ed into OP if operand is a range */
- X
- X#define OP_BASE 256
- X#define ACOS OP_BASE + 0
- X#define ASIN OP_BASE + 1
- X#define ATAN OP_BASE + 2
- X#define CEIL OP_BASE + 3
- X#define COS OP_BASE + 4
- X#define EXP OP_BASE + 5
- X#define FABS OP_BASE + 6
- X#define FLOOR OP_BASE + 7
- X#define HYPOT OP_BASE + 8
- X#define LOG OP_BASE + 9
- X#define LOG10 OP_BASE + 10
- X#define POW OP_BASE + 11
- X#define SIN OP_BASE + 12
- X#define SQRT OP_BASE + 13
- X#define TAN OP_BASE + 14
- X#define DTR OP_BASE + 15
- X#define RTD OP_BASE + 16
- X#define MIN OP_BASE + 17
- X#define MAX OP_BASE + 18
- X#define RND OP_BASE + 19
- X#define HOUR OP_BASE + 20
- X#define MINUTE OP_BASE + 21
- X#define SECOND OP_BASE + 22
- X#define MONTH OP_BASE + 23
- X#define DAY OP_BASE + 24
- X#define YEAR OP_BASE + 25
- X#define NOW OP_BASE + 26
- X#define DATE OP_BASE + 27
- X#define FMT OP_BASE + 28
- X#define SUBSTR OP_BASE + 29
- X#define STON OP_BASE + 30
- X#define EQS OP_BASE + 31
- X#define EXT OP_BASE + 32
- X#define ELIST OP_BASE + 33 /* List of expressions */
- X#define LMAX OP_BASE + 34
- X#define LMIN OP_BASE + 35
- X#define NVAL OP_BASE + 36
- X#define SVAL OP_BASE + 37
- X#define PV OP_BASE + 38
- X#define FV OP_BASE + 39
- X#define PMT OP_BASE + 40
- X#define STINDEX OP_BASE + 41
- X#define LOOKUP OP_BASE + 42
- X#define ATAN2 OP_BASE + 43
- X#define INDEX OP_BASE + 44
- X#define DTS OP_BASE + 45
- X#define TTS OP_BASE + 46
- X#define ABS OP_BASE + 47
- X#define HLOOKUP OP_BASE + 48
- X#define VLOOKUP OP_BASE + 49
- X#define ROUND OP_BASE + 50
- X#define IF OP_BASE + 51
- X
- X/* flag values */
- X#define is_valid 0001
- X#define is_changed 0002
- X#define is_strexpr 0004
- X#define is_leftflush 0010
- X#define is_deleted 0020
- X
- X#define ctl(c) ((c)&037)
- X#define ESC 033
- X#define DEL 0177
- X
- X#define BYCOLS 1
- X#define BYROWS 2
- X#define BYGRAPH 4 /* Future */
- X
- X#define TBL 1 /* tblprint style output for 'tbl' */
- X#define LATEX 2 /* tblprint style output for 'LaTeX' */
- X#define TEX 3 /* tblprint style output for 'TeX' */
- X
- X/* Types for etype() */
- X
- X#define NUM 1
- X#define STR 2
- X
- X#define GROWAMT 10 /* default minimum amount to grow */
- X
- X#define GROWNEW 1 /* first time table */
- X#define GROWROW 2 /* add rows */
- X#define GROWCOL 3
- X#define GROWBOTH 4
- Xextern struct ent ***tbl;
- X
- Xextern char curfile[];
- Xextern int strow, stcol;
- Xextern int currow, curcol;
- Xextern int savedrow, savedcol;
- Xextern int FullUpdate;
- Xextern int maxrow, maxcol;
- Xextern int maxrows, maxcols; /* # cells currently allocated */
- Xextern int *fwidth;
- Xextern int *precision;
- Xextern char *col_hidden;
- Xextern char *row_hidden;
- Xextern char line[FBUFLEN];
- Xextern int linelim;
- Xextern int changed;
- Xextern struct ent *to_fix;
- Xextern int showsc, showsr;
- X
- Xextern FILE *openout();
- Xextern char *coltoa();
- Xextern char *findhome();
- Xextern char *r_name();
- Xextern char *seval();
- Xextern char *strrchr();
- Xextern char *v_name();
- Xextern char *xmalloc();
- Xextern double dolookup();
- Xextern double eval();
- Xextern int RealEvalAll();
- Xextern int are_ranges();
- Xextern int atocol();
- Xextern int constant();
- Xextern int etype();
- Xextern int fork();
- Xextern int get_rcqual();
- Xextern int growtbl();
- Xextern int nmgetch();
- Xextern int writefile();
- Xextern int xfree();
- Xextern int yn_ask();
- Xextern struct enode *copye();
- Xextern struct enode *new();
- Xextern struct enode *new_const();
- Xextern struct enode *new_range();
- Xextern struct enode *new_str();
- Xextern struct enode *new_var();
- Xextern struct ent *lookat();
- Xextern struct range *find_range();
- Xextern void EvalAll();
- Xextern void Evalall();
- Xextern void RealEvalOne();
- Xextern void backcol();
- Xextern void backrow();
- Xextern void checkbounds();
- Xextern void clearent();
- Xextern void closecol();
- Xextern void closeout();
- Xextern void closerow();
- Xextern void colshow_op();
- Xextern void colvalueize();
- Xextern void colvalueize();
- Xextern void copy();
- Xextern void copyent();
- Xextern void copyrtv();
- Xextern void decompile();
- Xextern void deletecol();
- Xextern void deleterow();
- Xextern void deraw();
- Xextern void doend();
- Xextern void doformat();
- Xextern void dupcol();
- Xextern void duprow();
- Xextern void editexp();
- Xextern void edits();
- Xextern void editv();
- Xextern void efree();
- Xextern void erase_area();
- Xextern void erasedb();
- Xextern void eraser();
- Xextern void fill();
- Xextern void flush_saved();
- Xextern void forwcol();
- Xextern void forwrow();
- Xextern void free_ent();
- Xextern void go_last();
- Xextern void goraw();
- Xextern void help();
- Xextern void hide_col();
- Xextern void hide_row();
- Xextern void hidecol();
- Xextern void hiderow();
- Xextern void index_arg();
- Xextern void ins_string();
- Xextern void insert_mode();
- Xextern void insertcol();
- Xextern void insertrow();
- Xextern void kbd_again();
- Xextern void label();
- Xextern void let();
- Xextern void list_arg();
- Xextern void list_range();
- Xextern void moveto();
- Xextern void num_search();
- Xextern void one_arg();
- Xextern void opencol();
- Xextern void openrow();
- Xextern void printfile();
- Xextern void pullcells();
- Xextern void range_arg();
- Xextern void readfile();
- Xextern void repaint();
- Xextern void resetkbd();
- Xextern void rowshow_op();
- Xextern void rowvalueize();
- Xextern void setauto();
- Xextern void setiterations();
- Xextern void setorder();
- Xextern void showcol();
- Xextern void showdr();
- Xextern void showrow();
- Xextern void showstring();
- Xextern void signals();
- Xextern void slet();
- Xextern void startshow();
- Xextern void str_search();
- Xextern void sync_refs();
- Xextern void syncref();
- Xextern void tblprintfile();
- Xextern void three_arg();
- Xextern void two_arg();
- Xextern void two_arg_index();
- Xextern void update();
- Xextern void valueize_area();
- Xextern void write_fd();
- Xextern void write_line();
- Xextern void yyerror();
- X#ifdef DOBACKUPS
- Xextern int backup_file();
- X#endif
- X
- Xextern int modflg;
- Xextern int Crypt;
- Xextern char *mdir;
- Xextern double prescale;
- Xextern int extfunc;
- Xextern int propagation;
- Xextern int calc_order;
- Xextern int autocalc;
- Xextern int numeric;
- Xextern int showcell;
- Xextern int showtop;
- Xextern int loading;
- Xextern int getrcqual;
- Xextern int tbl_style;
- Xextern char *progname;
- X
- X#if BSD42 || SYSIII
- X
- X#ifndef cbreak
- X#define cbreak crmode
- X#define nocbreak nocrmode
- X#endif
- X
- X#endif
- END_OF_FILE
- if test 8426 -ne `wc -c <'sc.h'`; then
- echo shar: \"'sc.h'\" unpacked with wrong size!
- fi
- # end of 'sc.h'
- fi
- if test -f 'version.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'version.c'\"
- else
- echo shar: Extracting \"'version.c'\" \(148 characters\)
- sed "s/^X//" >'version.c' <<'END_OF_FILE'
- X/*
- X * CODE REVISION NUMBER:
- X *
- X * The part after the first colon, except the last char, appears on the screen.
- X */
- X
- Xchar *rev = "$Revision: 6.8 $";
- END_OF_FILE
- if test 148 -ne `wc -c <'version.c'`; then
- echo shar: \"'version.c'\" unpacked with wrong size!
- fi
- # end of 'version.c'
- fi
- if test -f 'vi.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vi.c'\"
- else
- echo shar: Extracting \"'vi.c'\" \(10584 characters\)
- sed "s/^X//" >'vi.c' <<'END_OF_FILE'
- X/* SC A Spreadsheet Calculator
- X *
- X * One line vi emulation
- X * $Revision: 6.8 $
- X */
- X
- X
- X#include <signal.h>
- X#include <curses.h>
- X
- X#ifdef BSD42
- X#include <strings.h>
- X#else
- X#ifndef SYSIII
- X#include <string.h>
- X#endif
- X#endif
- X
- X#if !defined(strchr) && !defined(UPORT)
- X#define strchr index
- X#endif
- Xextern char *strchr();
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "sc.h"
- X
- X#define istext(a) (isalnum(a) || ((a) == '_'))
- X
- Xextern int showrange;
- Xextern char mode_ind; /* Mode indicator */
- X
- X/* values for mode below */
- X
- X#define INSERT_MODE 0 /* Insert mode */
- X#define EDIT_MODE 1 /* Edit mode */
- X#define REP_MODE 2 /* Replace mode */
- X#define SEARCH_MODE 3 /* Get arguments for '/' command */
- X
- Xstatic int mode = INSERT_MODE;
- Xstatic char *history[HISTLEN];
- Xstatic int histp = -1;
- Xstatic char *last_search;
- Xstatic char *undo_line;
- Xstatic int undo_lim;
- Xstatic char dotb[100];
- Xstatic int doti = 0;
- Xstatic int do_dot = 0;
- X
- Xvoid
- Xwrite_line(c)
- Xint c;
- X{
- X if (mode == EDIT_MODE) {
- X switch(c) {
- X case (ctl('h')): linelim = back_line(); break;
- X case (ctl('m')): cr_line(); break;
- X case ESC: stop_edit(); break;
- X case '+': for_hist(); break;
- X case '-': back_hist(); break;
- X case '$': last_col(); break;
- X case '.': dotcmd(); break;
- X case '/': search_mode(); break;
- X case '0': col_0(); break;
- X case 'D': u_save(c);del_to_end(); break;
- X case 'I': u_save(c);col_0();insert_mode();break;
- X case 'R': replace_mode(); break;
- X case 'X': u_save(c); back_space(); break;
- X case 'a': u_save(c); append_line(); break;
- X case 'b': linelim = back_word(); break;
- X case 'c': u_save(c); change_cmd(); break;
- X case 'd': u_save(c); delete_cmd(); break;
- X case 'f': linelim = find_char(); break;
- X case 'h': linelim = back_line(); break;
- X case 'i': u_save(c); insert_mode(); break;
- X case 'j': for_hist(); break;
- X case 'k': back_hist(); break;
- X case 'l': linelim = for_line(0); break;
- X case 'n': search_again(); break;
- X case 'q': stop_edit(); break;
- X case 'r': u_save(c); rep_char(); break;
- X case 't': linelim = to_char(); break;
- X case 'u': restore_it(); break;
- X case 'w': linelim = for_word(0); break;
- X case 'x': u_save(c); del_in_line(); break;
- X default: break;
- X }
- X } else if (mode == INSERT_MODE) {
- X savedot(c);
- X switch(c) {
- X case (ctl('h')): back_space(); break;
- X case (ctl('m')): cr_line(); break;
- X case ESC: edit_mode(); break;
- X default: ins_in_line(c); break;
- X }
- X } else if (mode == SEARCH_MODE) {
- X switch(c) {
- X case (ctl('h')): back_space(); break;
- X case (ctl('m')): search_hist(); break;
- X case ESC: edit_mode(); break;
- X default: ins_in_line(c); break;
- X }
- X } else if (mode == REP_MODE) {
- X savedot(c);
- X switch(c) {
- X case (ctl('h')): back_space(); break;
- X case (ctl('m')): cr_line(); break;
- X case ESC: edit_mode(); break;
- X default: replace_in_line(c); break;
- X }
- X }
- X}
- X
- Xedit_mode()
- X{
- X mode = EDIT_MODE;
- X mode_ind = 'e';
- X histp = -1;
- X if (line[linelim] == '\0')
- X linelim = back_line();
- X}
- X
- Xvoid
- Xinsert_mode()
- X{
- X mode_ind = 'i';
- X mode = INSERT_MODE;
- X}
- X
- Xsearch_mode()
- X{
- X line[0] = '/';
- X line[1] = 0;
- X linelim = 1;
- X histp = -1;
- X mode_ind = '/';
- X mode = SEARCH_MODE;
- X}
- X
- Xreplace_mode()
- X{
- X mode_ind = 'R';
- X mode = REP_MODE;
- X}
- X
- X/* dot command functions. Saves info so we can redo on a '.' command */
- X
- Xsavedot(c)
- Xint c;
- X{
- X if (do_dot)
- X return;
- X
- X dotb[doti++] = c;
- X dotb[doti] = 0;
- X}
- X
- Xdotcmd()
- X{
- X int c;
- X
- X do_dot = 1;
- X doti = 0;
- X while(dotb[doti] != 0) {
- X c = dotb[doti++];
- X write_line(c);
- X }
- X do_dot = 0;
- X doti = 0;
- X}
- X
- Xvigetch()
- X{
- X int c;
- X
- X if(do_dot) {
- X if (dotb[doti] != 0) {
- X return(dotb[doti++]);
- X } else {
- X do_dot = 0;
- X doti = 0;
- X return(nmgetch());
- X }
- X }
- X c = nmgetch();
- X savedot(c);
- X return(c);
- X}
- X
- X/* saves the current line for possible use by an undo cmd */
- X
- Xu_save(c)
- Xint c;
- X{
- X if (undo_line) {
- X xfree(undo_line);
- X undo_line = 0;
- X }
- X undo_line = strcpy(xmalloc((unsigned)(strlen(line)+1)), line);
- X undo_lim = linelim;
- X
- X /* reset dot command if not processing it. */
- X
- X if (!do_dot) {
- X doti = 0;
- X savedot(c);
- X }
- X}
- X
- X/* Restores the current line saved by u_save() */
- X
- Xrestore_it()
- X{
- X register char *tempc;
- X register int tempi;
- X
- X if (!undo_line)
- X return;
- X tempc = strcpy(xmalloc((unsigned)(strlen(line)+1)), line);
- X tempi = linelim;
- X strcpy(line, undo_line);
- X linelim = undo_lim;
- X xfree(undo_line);
- X undo_line = tempc;
- X undo_lim = tempi;
- X}
- X
- X/* This command stops the editing process. */
- X
- Xstop_edit()
- X{
- X showrange = 0;
- X linelim = -1;
- X (void) move(1, 0);
- X (void) clrtoeol();
- X}
- X
- X/*
- X * Motion commands. Forward motion commands take an argument
- X * which, when set, cause the forward motion to continue onto
- X * the null at the end of the line instead of stopping at the
- X * the last character of the line.
- X */
- X
- Xfor_line(stop_null)
- Xint stop_null;
- X{
- X if (linelim >= 0 && line[linelim] != 0 &&
- X (line[linelim+1] != 0 || stop_null))
- X return(linelim+1);
- X else
- X return(linelim);
- X}
- X
- Xfor_word(stop_null)
- Xint stop_null;
- X{
- X register int c;
- X register int cpos;
- X
- X cpos = linelim;
- X
- X if (line[cpos] == ' ') {
- X while (line[cpos] == ' ')
- X cpos++;
- X if (cpos > 0 && line[cpos] == 0)
- X --cpos;
- X return(cpos);
- X }
- X
- X if (istext(line[cpos])) {
- X while ((c = line[cpos]) && istext(c))
- X cpos++;
- X } else {
- X while ((c = line[cpos]) && !istext(c) && c != ' ')
- X cpos++;
- X }
- X
- X while (line[cpos] == ' ')
- X cpos++;
- X
- X if (cpos > 0 && line[cpos] == 0 && !stop_null)
- X --cpos;
- X
- X return(cpos);
- X}
- X
- Xback_line()
- X{
- X if (linelim)
- X return(linelim-1);
- X else
- X return(0);
- X}
- X
- Xback_word()
- X{
- X register int c;
- X register int cpos;
- X
- X cpos = linelim;
- X
- X if (line[cpos] == ' ') {
- X /* Skip white space */
- X while (cpos > 0 && line[cpos] == ' ')
- X --cpos;
- X } else if (cpos > 0 && (line[cpos-1] == ' '
- X || istext(line[cpos]) && !istext(line[cpos-1])
- X || !istext(line[cpos]) && istext(line[cpos-1]))) {
- X /* Started on the first char of a word - back up to prev. word */
- X --cpos;
- X while (cpos > 0 && line[cpos] == ' ')
- X --cpos;
- X }
- X
- X /* Skip across the word - goes 1 too far */
- X if (istext(line[cpos])) {
- X while (cpos > 0 && (c = line[cpos]) && istext(c))
- X --cpos;
- X } else {
- X while (cpos > 0 && (c = line[cpos]) && !istext(c) && c != ' ')
- X --cpos;
- X }
- X
- X /* We are done - fix up the one too far */
- X if (cpos > 0 && line[cpos] && line[cpos+1])
- X cpos++;
- X
- X return(cpos);
- X}
- X
- X/* Text manipulation commands */
- X
- Xdel_in_line()
- X{
- X register int len, i;
- X
- X if (linelim >= 0) {
- X len = strlen(line);
- X if (linelim == len && linelim > 0)
- X linelim--;
- X for (i = linelim; i < len; i++)
- X line[i] = line[i+1];
- X }
- X if (linelim > 0 && line[linelim] == 0)
- X --linelim;
- X}
- X
- Xins_in_line(c)
- Xint c;
- X{
- X register int i, len;
- X
- X len = strlen(line);
- X for (i = len; i >= linelim; --i)
- X line[i+1] = line[i];
- X line[linelim++] = c;
- X line[len+1] = 0;
- X}
- X
- Xvoid
- Xins_string(s)
- Xchar *s;
- X{
- X while (*s)
- X ins_in_line(*s++);
- X}
- X
- Xappend_line()
- X{
- X register int i;
- X
- X i = linelim;
- X if (i >= 0 && line[i])
- X linelim++;
- X insert_mode();
- X}
- X
- Xrep_char()
- X{
- X int c;
- X
- X c = vigetch();
- X if (line[linelim] != 0) {
- X line[linelim] = c;
- X } else {
- X line[linelim] = c;
- X line[linelim+1] = 0;
- X }
- X}
- X
- Xreplace_in_line(c)
- X{
- X register int len;
- X
- X len = strlen(line);
- X line[linelim++] = c;
- X if (linelim > len)
- X line[linelim] = 0;
- X}
- X
- Xback_space()
- X{
- X if (linelim == 0)
- X return;
- X
- X if (line[linelim] == 0) {
- X linelim = back_line();
- X del_in_line();
- X linelim = strlen(line);
- X } else {
- X linelim = back_line();
- X del_in_line();
- X }
- X}
- X
- Xget_motion()
- X{
- X int c;
- X
- X c = vigetch();
- X switch (c) {
- X case 'b': return(back_word());
- X case 'f': return(find_char()+1);
- X case 'h': return(back_line());
- X case 'l': return(for_line(1));
- X case 't': return(to_char()+1);
- X case 'w': return(for_word(1));
- X default: return(linelim);
- X }
- X}
- X
- Xdelete_cmd()
- X{
- X int cpos;
- X
- X cpos = get_motion();
- X del_chars(cpos, linelim);
- X}
- X
- Xchange_cmd()
- X{
- X delete_cmd();
- X insert_mode();
- X}
- X
- Xdel_chars(first, last)
- Xregister int first, last;
- X{
- X int temp;
- X
- X if (first == last)
- X return;
- X
- X if (last < first) {
- X temp = last; last = first; first = temp;
- X }
- X
- X linelim = first;
- X while(first < last) {
- X del_in_line();
- X --last;
- X }
- X}
- X
- Xdel_to_end()
- X{
- X if (linelim < 0)
- X return;
- X line[linelim] = 0;
- X linelim = back_line();
- X}
- X
- Xcr_line()
- X{
- X showrange = 0;
- X insert_mode();
- X save_hist();
- X linelim = 0;
- X (void) yyparse ();
- X linelim = -1;
- X}
- X
- X/* History functions */
- X
- Xsave_hist()
- X{
- X register int i;
- X
- X /* free the oldest one */
- X if (history[HISTLEN-1]) {
- X xfree(history[HISTLEN-1]);
- X history[HISTLEN-1] = 0;
- X }
- X
- X /* Move the others back */
- X for (i = HISTLEN-1; i > 0; --i)
- X history[i] = history[i-1];
- X
- X history[0] = xmalloc((unsigned) strlen(line)+1);
- X strcpy(history[0], line);
- X}
- X
- Xback_hist()
- X{
- X if (histp == -1 || histp < HISTLEN-1 && history[histp + 1])
- X histp++;
- X
- X if (history[histp]) {
- X strcpy(line, history[histp]);
- X linelim = 0;
- X } else
- X line[linelim = 0] = 0;
- X
- X}
- X
- Xsearch_hist()
- X{
- X if (last_search) {
- X xfree(last_search);
- X last_search = 0;
- X }
- X
- X if(linelim < 1) {
- X linelim = 0;
- X edit_mode();
- X return;
- X }
- X
- X last_search = strcpy(xmalloc((unsigned)(strlen(line+1)+1)), line+1);
- X search_again();
- X mode = EDIT_MODE;
- X}
- X
- Xsearch_again()
- X{
- X int found_it;
- X int do_next;
- X int prev_histp;
- X char *look_here;
- X
- X prev_histp = histp;
- X if (!last_search)
- X return;
- X
- X do {
- X back_hist();
- X if (prev_histp == histp)
- X break;
- X prev_histp = histp;
- X look_here = line;
- X found_it = do_next = 0;
- X while ((look_here = strchr(look_here, last_search[0])) &&
- X !found_it && !do_next) {
- X
- X if (strncmp(look_here, last_search, strlen(last_search)) == 0)
- X found_it++;
- X else if (look_here < line + strlen(line) - 1)
- X look_here++;
- X else
- X do_next++;
- X }
- X } while (!found_it);
- X}
- X
- Xfor_hist()
- X{
- X if (histp > 0)
- X histp--;
- X
- X if (histp >= 0 && history[histp]) {
- X strcpy(line, history[histp]);
- X linelim = 0;
- X } else
- X line[linelim = 0] = 0;
- X}
- X
- Xcol_0()
- X{
- X linelim = 0;
- X}
- X
- Xlast_col()
- X{
- X linelim = strlen(line);
- X if (linelim > 0)
- X --linelim;
- X}
- X
- Xfind_char()
- X{
- X register int c;
- X register int i;
- X
- X
- X c = vigetch();
- X i = linelim;
- X while(line[i] && line[i] != c)
- X i++;
- X if (!line[i])
- X i = linelim;
- X return(i);
- X}
- X
- Xto_char()
- X{
- X register int i;
- X
- X i = find_char();
- X if (i > 0 && i != linelim)
- X --i;
- X
- X return(i);
- X}
- END_OF_FILE
- if test 10584 -ne `wc -c <'vi.c'`; then
- echo shar: \"'vi.c'\" unpacked with wrong size!
- fi
- # end of 'vi.c'
- fi
- if test -f 'vmtbl.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vmtbl.c'\"
- else
- echo shar: Extracting \"'vmtbl.c'\" \(4643 characters\)
- sed "s/^X//" >'vmtbl.c' <<'END_OF_FILE'
- X#ifdef PSC
- X# include <stdio.h>
- X# include "sc.h"
- X# ifndef FALSE
- X# define FALSE 0
- X# define TRUE 1
- X# endif /* !FALSE */
- X# undef error
- X# define error(msg) fprintf(stderr, msg);
- X#else /* PSC */
- X# include <curses.h>
- X# include "sc.h"
- X#endif /* PSC */
- X
- Xextern char *malloc();
- Xextern char *realloc();
- X
- X#if defined(BSD42) || defined(BSD43)
- X#define memcpy(dest, source, len) bcopy(source, dest, (unsigned int)len);
- X#define memset(dest, zero, len) bzero((dest), (unsigned int)(len));
- X#endif
- X
- X/*
- X * check to see if *rowp && *colp are currently allocated, if not expand the
- X * current size if we can.
- X */
- X#ifndef PSC
- Xvoid
- Xcheckbounds(rowp, colp)
- Xint *rowp;
- Xint *colp;
- X{
- X if (*rowp < 0)
- X *rowp = 0;
- X else if (*rowp >= maxrows)
- X { if (*colp >= maxcols)
- X { if (!growtbl(GROWBOTH, *rowp, *colp))
- X { *rowp = maxrows -1;
- X *colp = maxcols -1;
- X }
- X return;
- X }
- X else
- X { if (!growtbl(GROWROW, *rowp, 0))
- X *rowp = maxrows-1;
- X return;
- X }
- X }
- X if (*colp < 0)
- X *colp = 0;
- X else if (*colp >= maxcols)
- X { if (!growtbl(GROWCOL, 0, *colp));
- X *colp = maxcols-1;
- X }
- X}
- X#endif /* !PSC */
- X
- X
- X#define GROWALLOC(newptr, oldptr, nelem, type, msg) \
- X if (oldptr == (type *)NULL) \
- X newptr = (type *)malloc((unsigned)(nelem*sizeof(type))); \
- X else \
- X newptr = (type *)realloc((char *)oldptr, \
- X (unsigned)(nelem*sizeof(type))); \
- X if (newptr == (type *)NULL) \
- X { error(msg); \
- X return(FALSE); \
- X } \
- X oldptr = newptr /* wait incase we can't alloc */
- X
- Xstatic char nolonger[] = "The table can't be any longer";
- Xstatic char nowider[] = "The table can't be any wider";
- X
- X/*
- X * grow the main && auxiliary tables (reset maxrows/maxcols as needed)
- X * toprow &&/|| topcol tell us a better guess of how big to become.
- X * we return TRUE if we could grow, FALSE if not....
- X */
- Xint
- Xgrowtbl(rowcol, toprow, topcol)
- Xint rowcol;
- Xint toprow, topcol;
- X{
- X struct ent ***tbl2;
- X int *fwidth2;
- X int *precision2;
- X char *col_hidden2;
- X char *row_hidden2;
- X int newrows, newcols;
- X int i;
- X
- X#ifndef PSC
- X newrows = maxrows;
- X#endif /* !PSC */
- X
- X newcols = maxcols;
- X if (rowcol == GROWNEW)
- X {
- X#ifndef PSC
- X maxrows = toprow = 0;
- X /* when we first start up, fill the screen w/ cells */
- X { int startval;
- X startval = LINES - RESROW;
- X newrows = startval > MINROWS ? startval : MINROWS;
- X startval = ((COLS) - RESCOL) / DEFWIDTH;
- X newcols = startval > MINCOLS ? startval : MINCOLS;
- X }
- X#else
- X newcols = MINCOLS;
- X#endif /* !PSC */
- X maxcols = topcol = 0;
- X }
- X#ifndef PSC
- X /* set how much to grow */
- X if ((rowcol == GROWROW) || (rowcol == GROWBOTH))
- X { if (toprow > maxrows)
- X newrows = GROWAMT + toprow;
- X else
- X newrows += GROWAMT;
- X }
- X#endif /* !PSC */
- X if ((rowcol == GROWCOL) || (rowcol == GROWBOTH))
- X { if ((rowcol == GROWCOL) && ((maxcols == ABSMAXCOLS) ||
- X (topcol >= ABSMAXCOLS)))
- X { error(nowider);
- X return(FALSE);
- X }
- X
- X if (topcol > maxcols)
- X newcols = GROWAMT + topcol;
- X else
- X newcols += GROWAMT;
- X
- X if (newcols > ABSMAXCOLS)
- X newcols = ABSMAXCOLS;
- X }
- X
- X#ifndef PSC
- X if ((rowcol == GROWROW) || (rowcol == GROWBOTH) || (rowcol == GROWNEW))
- X {
- X GROWALLOC(row_hidden2, row_hidden, newrows, char, nolonger);
- X memset(row_hidden+maxrows, 0, (newrows-maxrows)*sizeof(char));
- X
- X /* alloc tbl row pointers */
- X GROWALLOC(tbl2, tbl, newrows, struct ent **, nolonger);
- X memset(tbl+maxrows, 0, (newrows-maxrows)*(sizeof(struct ent **)));
- X }
- X#endif /* !PSC */
- X
- X if ((rowcol == GROWCOL) || (rowcol == GROWBOTH) || (rowcol == GROWNEW))
- X {
- X GROWALLOC(fwidth2, fwidth, newcols, int, nowider);
- X GROWALLOC(precision2, precision, newcols, int, nowider);
- X#ifdef PSC
- X memset(fwidth+maxcols, 0, (newcols-maxcols)*sizeof(int));
- X memset(precision+maxcols, 0, (newcols-maxcols)*sizeof(int));
- X }
- X#else
- X GROWALLOC(col_hidden2, col_hidden, newcols, char, nowider);
- X memset(col_hidden+maxcols, 0, (newcols-maxcols)*sizeof(char));
- X for (i = maxcols; i < newcols; i++) {
- X fwidth[i] = DEFWIDTH;
- X precision[i] = DEFPREC;
- X }
- X
- X /* [re]alloc the space for each row */
- X for (i = 0; i < maxrows; i++)
- X {
- X if ((tbl[i] = (struct ent **)realloc((char *)tbl[i],
- X (unsigned)(newcols * sizeof(struct ent **)))) == (struct ent **)0)
- X { error(nowider);
- X return(FALSE);
- X }
- X memset((char *)ATBL(tbl,i, maxcols), 0,
- X (newcols-maxcols)*sizeof(struct ent **));
- X }
- X }
- X else
- X i = maxrows;
- X
- X /* fill in the bottom of the table */
- X for (; i < newrows; i++)
- X { if ((tbl[i] = (struct ent **)malloc((unsigned)(newcols *
- X sizeof(struct ent **)))) == (struct ent **)0)
- X { error(nowider);
- X return(FALSE);
- X }
- X memset((char *)tbl[i], 0, newcols*sizeof(struct ent **));
- X }
- X
- X FullUpdate++;
- X maxrows = newrows;
- X#endif /* PSC */
- X
- X maxcols = newcols;
- X return(TRUE);
- X}
- END_OF_FILE
- if test 4643 -ne `wc -c <'vmtbl.c'`; then
- echo shar: \"'vmtbl.c'\" unpacked with wrong size!
- fi
- # end of 'vmtbl.c'
- fi
- echo shar: End of archive 5 \(of 6\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-